package com.baomidou.mybatisplus.ext.processor;

import com.baomidou.mybatisplus.ext.util.AstUtil;
import com.baomidou.mybatisplus.ext.anno.Wrapperable;
import com.google.auto.service.AutoService;
import com.sun.source.tree.Tree;
import com.sun.source.util.Trees;
import com.sun.tools.javac.api.JavacTrees;
import com.sun.tools.javac.code.Flags;
import com.sun.tools.javac.model.JavacElements;
import com.sun.tools.javac.processing.JavacProcessingEnvironment;
import com.sun.tools.javac.tree.JCTree;
import com.sun.tools.javac.tree.TreeMaker;
import com.sun.tools.javac.tree.TreeTranslator;
import com.sun.tools.javac.util.*;

import javax.annotation.processing.*;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.Element;
import javax.lang.model.element.TypeElement;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;

/**
 * 给PO添加 eq,neq,like,likeLeft,likeRight,in,notin,between,notbetween,isNull,isNotNull,orderBy,orderByDesc,orderByAsc，list,newOBJ,one,update,delete 方法
 * 如果你要修改此段代码，请准备好速效救心丸，JCTree 相关技术网上资料不多，请多参数github上的代码
 *
 * @author wanglei
 */
@SupportedAnnotationTypes("com.baomidou.mybatisplus.ext.anno.Wrapperable")
@SupportedSourceVersion(SourceVersion.RELEASE_8)
@AutoService(Processor.class)
public class WrapperAnnotationProcessor extends AbstractProcessor {
    private Messager messager;

    private Context context;

    private JavacElements elementUtils;

    private TreeMaker treeMaker;

    private JavacTrees javacTrees;

    private Filer mFiler;

    private Set<String> stringSet = new TreeSet<>();

    private Names names;

    private Trees trees;

    @Override
    public synchronized void init(ProcessingEnvironment processingEnv) {
        trees = Trees.instance(processingEnv);
        messager = processingEnv.getMessager();
        context = ((JavacProcessingEnvironment) processingEnv).getContext();
        elementUtils = (JavacElements) processingEnv.getElementUtils();
        treeMaker = TreeMaker.instance(context);
        javacTrees = JavacTrees.instance(processingEnv);
        mFiler = processingEnv.getFiler();
        super.init(processingEnv);
        names = Names.instance(context);
    }


    @Override
    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {


        //获取注解标识的类集合
        Set<? extends Element> set = roundEnv.getElementsAnnotatedWith(Wrapperable.class);
        for (Element element : set) {
            //获取语法树的根节点
            JCTree tree = javacTrees.getTree(element);
            //添加访问事件
            tree.accept(new TreeTranslator() {
                @Override
                public void visitClassDef(JCTree.JCClassDecl jcClassDecl) {
                    try {
                        //定义一个变量叫做  wrapper
                        jcClassDecl.defs = jcClassDecl.defs.prepend(genWrapperField(jcClassDecl));

                        Map<String, List<JCTree.JCVariableDecl>> hasMethod = new HashMap<>();
                        jcClassDecl.defs.stream()
                                //开始过滤: 只对变量进行处理
                                .filter(it -> it.getKind().equals(Tree.Kind.METHOD))
                                //强制类型转换
                                .map(it -> (JCTree.JCMethodDecl) it).forEach(it -> {
                                    hasMethod.put(it.name.toString(), it.params);
                                });

                        //------------------------------下面代码后面考虑用设计模式处理，我也觉得有点恶心，暂时先这样处理---------------------------------

                        try {


                            //生成bean2Wrapper方法
                            if (!hasMethod.containsKey("bean2Wrapper")) {
                                jcClassDecl.defs = jcClassDecl.defs.prepend(genBean2WrapperMethod(jcClassDecl));
                            }

                            if (!hasMethod.containsKey("list")) {
                                //生成list(String[] feilds)方法
                                jcClassDecl.defs = jcClassDecl.defs.prepend(genListSettFieldsMethod(jcClassDecl));
                                //生成list()方法
                                jcClassDecl.defs = jcClassDecl.defs.prepend(genListMethod(jcClassDecl));
                            }

                            if (!hasMethod.containsKey("one")) {
                                //生成one(String[] feilds)方法
                                jcClassDecl.defs = jcClassDecl.defs.prepend(genOneSettFieldsMethod(jcClassDecl));
                                //生成one()方法
                                jcClassDecl.defs = jcClassDecl.defs.prepend(genOneMethod(jcClassDecl));
                            }

                            if (!hasMethod.containsKey("count")) {
                                //生成count方法
                                jcClassDecl.defs = jcClassDecl.defs.prepend(genCountMethod(jcClassDecl));
                            }

                            if (!hasMethod.containsKey("update")) {
                                //生成update方法
                                jcClassDecl.defs = jcClassDecl.defs.prepend(genUpdateMethod(jcClassDecl));
                            }

                            if (!hasMethod.containsKey("delete")) {
                                //生成delete方法
                                jcClassDecl.defs = jcClassDecl.defs.prepend(genDeleteMethod(jcClassDecl));
                            }


                            //生成newOBJ方法 public static PO newOBJ
                            if (!hasMethod.containsKey("newOBJ")) {
                                jcClassDecl.defs = jcClassDecl.defs.prepend(genNewObjMethod(jcClassDecl));
                            }
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                        //
                        jcClassDecl.defs.stream()
                                //开始过滤: 只对变量进行处理
                                .filter(it -> it.getKind().equals(Tree.Kind.VARIABLE))
                                //强制类型转换
                                .map(it -> (JCTree.JCVariableDecl) it)
                                //处理: 生成Getter方法和Setter方法
                                .forEach(it -> {
                                            if (isHandle(it, jcClassDecl)) {
                                                jcClassDecl.defs = jcClassDecl.defs.prepend(genFieldNameField(it));
                                                //拼接通用方法
                                                jcClassDecl.defs = jcClassDecl.defs.prepend(genEQMethod(it, jcClassDecl));
                                                jcClassDecl.defs = jcClassDecl.defs.prepend(genNEQMethod(it, jcClassDecl));
                                                jcClassDecl.defs = jcClassDecl.defs.prepend(genGEMethod(it, jcClassDecl));
                                                jcClassDecl.defs = jcClassDecl.defs.prepend(genGTMethod(it, jcClassDecl));
                                                jcClassDecl.defs = jcClassDecl.defs.prepend(genLEMethod(it, jcClassDecl));
                                                jcClassDecl.defs = jcClassDecl.defs.prepend(genLTMethod(it, jcClassDecl));
                                                jcClassDecl.defs = jcClassDecl.defs.prepend(genOrderByAscMethod(it, jcClassDecl));
                                                jcClassDecl.defs = jcClassDecl.defs.prepend(genOrderByDescMethod(it, jcClassDecl));
                                                jcClassDecl.defs = jcClassDecl.defs.prepend(genIsNullMethod(it, jcClassDecl));
                                                jcClassDecl.defs = jcClassDecl.defs.prepend(genNotNullMethod(it, jcClassDecl));
                                                jcClassDecl.defs = jcClassDecl.defs.prepend(genInMethod(it, jcClassDecl));
                                                jcClassDecl.defs = jcClassDecl.defs.prepend(genNotInMethod(it, jcClassDecl));
                                                jcClassDecl.defs = jcClassDecl.defs.prepend(genBetweenMethod(it, jcClassDecl));
                                                jcClassDecl.defs = jcClassDecl.defs.prepend(genNotBetweenMethod(it, jcClassDecl));
                                                //字符串特有的like 方法拼接
                                                if (checkIsCharset(it, jcClassDecl)) {
                                                    jcClassDecl.defs = jcClassDecl.defs.prepend(genLikeMethod(it, jcClassDecl));
                                                    jcClassDecl.defs = jcClassDecl.defs.prepend(genLikeRightMethod(it, jcClassDecl));
                                                    jcClassDecl.defs = jcClassDecl.defs.prepend(genLikeLeftMethod(it, jcClassDecl));
                                                    jcClassDecl.defs = jcClassDecl.defs.prepend(genNotLikeMethod(it, jcClassDecl));
                                                }
                                            }

                                        }
                                );
                        super.visitClassDef(jcClassDecl);

                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            });
        }

        return true;
    }

    /**
     * 生成mapper的interface代码
     * @param jcClassDecl
     * @return
     */
    public JCTree.JCClassDecl genMapperInterface(JCTree.JCClassDecl jcClassDecl) {
        JCTree.JCTypeApply implInterface = treeMaker.TypeApply(AstUtil.memberAccess(treeMaker, elementUtils, "com.baomidou.mybatisplus.core.mapper.BaseMapper"),
                List.of(AstUtil.memberAccess(treeMaker, elementUtils, jcClassDecl.sym.toString())));
        return treeMaker.ClassDef(
                treeMaker.Modifiers(Flags.PUBLIC + Flags.STATIC + Flags.INTERFACE, List.nil()),
                names.fromString(jcClassDecl.getSimpleName() + "Mapper"),
                List.nil(),
                null,
                List.of(implInterface), List.nil());
    }

    /**
     * 添加常量字段 比如 字段里有一个name 这里就帮他生成一个NAME
     *
     * @param jcVariableDecl
     * @return
     */
    private JCTree.JCVariableDecl genFieldNameField(JCTree.JCVariableDecl jcVariableDecl) {
        //方法参数: 方法的形式参数 Collection<?> collection
        JCTree.JCVariableDecl result = treeMaker.VarDef(
                treeMaker.Modifiers(Flags.PUBLIC + Flags.STATIC + Flags.FINAL, List.nil()),  //访问变量标识符
                names.fromString(jcVariableDecl.name.toString().toUpperCase()),        //变量名
                AstUtil.memberAccess(treeMaker, elementUtils, "java.lang.String"),     //变量类型
                treeMaker.Literal(jcVariableDecl.name.toString())        //变量初始值
        );
        return result;
    }

    /**
     * 添加wrapper字段
     *
     * @param jcClassDecl
     * @return
     */
    private JCTree.JCVariableDecl genWrapperField(JCTree.JCClassDecl jcClassDecl) {


        List<JCTree.JCExpression> constructorParams = List.nil();
        JCTree.JCVariableDecl result = AstUtil.addField(treeMaker, elementUtils, names,
                "com.baomidou.mybatisplus.core.conditions.query.QueryWrapper",
                "wrapper", List.nil());
        //添加忽略字段注解
        result.mods.annotations = result.mods.annotations.append(treeMaker.Annotation(AstUtil.memberAccess(treeMaker, elementUtils,
                "com.baomidou.mybatisplus.annotation.TableField"), List.of(treeMaker.Assign(treeMaker.Ident(names.fromString("exist")), treeMaker.Literal(false)))));

        //fastjson不序列化
        result.mods.annotations = result.mods.annotations.append(treeMaker.Annotation(AstUtil.memberAccess(treeMaker, elementUtils,
                "com.alibaba.fastjson.annotation.JSONField"), List.of(treeMaker.Assign(treeMaker.Ident(names.fromString("serialize")), treeMaker.Literal(false)))));

        //jackson不序列化
        result.mods.annotations = result.mods.annotations.append(treeMaker.Annotation(AstUtil.memberAccess(treeMaker, elementUtils,
                "com.fasterxml.jackson.annotation.JsonIgnore"), List.nil()));
        return result;
    }

    /**
     * 构造集合 参数的方法 返回this
     *
     * @param jcVariableDecl 变量
     * @param jcClassDecl    类
     * @param methodNameStr  方法名
     * @param operator       操作符
     * @return
     */
    private JCTree.JCMethodDecl genParamCollectionMethod(JCTree.JCVariableDecl jcVariableDecl, JCTree.JCClassDecl jcClassDecl,
                                                         String methodNameStr, String operator) {
        // 生成 调用方法的参数列表
        List<JCTree.JCExpression> execFunparamsList = List.nil();
        // 参数添加this.wrapper
        execFunparamsList = execFunparamsList.append(treeMaker.Select(
                treeMaker.Ident(names.fromString("this"))
                , names.fromString("wrapper")
        ));

        // 操作符
        execFunparamsList = execFunparamsList.append(treeMaker.Literal(operator));

        // po
        execFunparamsList = execFunparamsList.append(treeMaker.Ident(names.fromString("this")));

        //属性名
        execFunparamsList = execFunparamsList.append(treeMaker.Literal(jcVariableDecl.name.toString()));

        //变量
        execFunparamsList = execFunparamsList.append(treeMaker.Ident(names.fromString("collection")));

        //方法参数: 方法的形式参数 Collection<?> collection
        JCTree.JCVariableDecl param = treeMaker.VarDef(
                treeMaker.Modifiers(Flags.PARAMETER, List.nil()),  //访问变量标识符
                names.fromString("collection"),        //变量名
                AstUtil.memberAccess(treeMaker, elementUtils, "java.util.Collection"),     //变量类型
                null        //变量初始值
        );

        List<JCTree.JCVariableDecl> genMethodParamsList = List.of(param);

        //生成return语句: return this;
        JCTree.JCReturn returnStatement = treeMaker.Return(
                treeMaker.Ident(names.fromString("this"))
        );
        String execMethodAllName = "com.baomidou.mybatisplus.ext.util.Funtions.addWrapper";
        return genMethod(
                execFunparamsList
                , genMethodParamsList,
                new String[]{"com.baomidou.mybatisplus.core.conditions.query.QueryWrapper", "java.lang.String",
                        "java.lang.Object", "java.lang.String", "java.lang.Object"},
                treeMaker.Ident(jcClassDecl.getSimpleName()), returnStatement, execMethodAllName, names.fromString(jcVariableDecl.getName() + methodNameStr));
    }


    /**
     * 构造2个参数或者没有参数的方法
     *
     * @param jcVariableDecl 变量
     * @param jcClassDecl    类
     * @param methodNameStr  方法名
     * @param operator       操作符
     * @return
     */
    private JCTree.JCMethodDecl gen2ParamMethod(JCTree.JCVariableDecl jcVariableDecl, JCTree.JCClassDecl jcClassDecl,
                                                String methodNameStr, String operator) {
        // 生成 调用方法的参数列表
        List<JCTree.JCExpression> execFunparamsList = List.nil();
        // 参数添加this.wrapperVars
        execFunparamsList = execFunparamsList.append(treeMaker.Select(
                treeMaker.Ident(names.fromString("this"))
                , names.fromString("wrapper")
        ));
        // 操作符
        execFunparamsList = execFunparamsList.append(treeMaker.Literal(operator));

        // po
        execFunparamsList = execFunparamsList.append(treeMaker.Ident(names.fromString("this")));

        //属性名
        execFunparamsList = execFunparamsList.append(treeMaker.Literal(jcVariableDecl.name.toString()));

        //变量min
        execFunparamsList = execFunparamsList.append(treeMaker.Ident(names.fromString(jcVariableDecl.name.toString() + "Min")));

        execFunparamsList = execFunparamsList.append(treeMaker.Ident(names.fromString(jcVariableDecl.name.toString() + "Max")));

        //参数值列表
        List<JCTree.JCVariableDecl> genMethodParamsList = List.nil();

        //方法参数: 方法的形式参数
        JCTree.JCVariableDecl paramMin = treeMaker.VarDef(
                treeMaker.Modifiers(Flags.PARAMETER, List.nil()),  //访问变量标识符
                names.fromString(jcVariableDecl.name.toString() + "Min"),        //变量名
                jcVariableDecl.vartype,     //变量类型
                null        //变量初始值
        );

        //方法参数: 方法的形式参数
        JCTree.JCVariableDecl paramMax = treeMaker.VarDef(
                treeMaker.Modifiers(Flags.PARAMETER, List.nil()),  //访问变量标识符
                names.fromString(jcVariableDecl.name.toString() + "Max"),        //变量名
                jcVariableDecl.vartype,     //变量类型
                null        //变量初始值
        );
        genMethodParamsList = List.of(paramMin).append(paramMax);

        //生成return语句: return this;
        JCTree.JCReturn returnStatement = treeMaker.Return(
                treeMaker.Ident(names.fromString("this"))
        );
        String execMethodAllName = "com.baomidou.mybatisplus.ext.util.Funtions.addWrapper";
        return genMethod(
                execFunparamsList
                , genMethodParamsList,
                new String[]{"com.baomidou.mybatisplus.core.conditions.query.QueryWrapper",
                        "java.lang.String", "java.lang.Object",
                        "java.lang.String", "java.lang.Object", "java.lang.Object"},
                treeMaker.Ident(jcClassDecl.getSimpleName()), returnStatement, execMethodAllName, names.fromString(jcVariableDecl.getName() + methodNameStr));
    }


    /**
     * 构造单个参数或者没有参数的方法
     *
     * @param jcVariableDecl 变量
     * @param jcClassDecl    类
     * @param isNeedParam    是否需要参数
     * @param methodNameStr  方法名
     * @param operator       操作符
     * @return
     */
    private JCTree.JCMethodDecl genMethod(JCTree.JCVariableDecl jcVariableDecl, JCTree.JCClassDecl jcClassDecl,
                                          boolean isNeedParam, String methodNameStr, String operator) {
        // 生成 调用方法的参数列表
        List<JCTree.JCExpression> execFunparamsList = List.nil();
        // 参数添加this.wrapperVars
        execFunparamsList = execFunparamsList.append(treeMaker.Select(
                treeMaker.Ident(names.fromString("this"))
                , names.fromString("wrapper")
        ));
        // 操作符
        execFunparamsList = execFunparamsList.append(treeMaker.Literal(operator));

        // po
        execFunparamsList = execFunparamsList.append(treeMaker.Ident(names.fromString("this")));

        //属性名
        execFunparamsList = execFunparamsList.append(treeMaker.Literal(jcVariableDecl.name.toString()));

        //变量
        execFunparamsList = execFunparamsList.append(isNeedParam ? treeMaker.Ident(jcVariableDecl.getName()) : treeMaker.Literal(true));

        //参数值列表
        List<JCTree.JCVariableDecl> genMethodParamsList = List.nil();
        if (isNeedParam) {
            //方法参数: 方法的形式参数
            JCTree.JCVariableDecl param = treeMaker.VarDef(
                    treeMaker.Modifiers(Flags.PARAMETER, List.nil()),  //访问变量标识符
                    jcVariableDecl.name,        //变量名
                    jcVariableDecl.vartype,     //变量类型
                    null        //变量初始值
            );

            genMethodParamsList = List.of(param);
        }

        //生成return语句: return this;
        JCTree.JCReturn returnStatement = treeMaker.Return(
                treeMaker.Ident(names.fromString("this"))
        );
        String execMethodAllName = "com.baomidou.mybatisplus.ext.util.Funtions.addWrapper";
        return genMethod(
                execFunparamsList
                , genMethodParamsList,
                new String[]{"com.baomidou.mybatisplus.core.conditions.query.QueryWrapper",
                        "java.lang.String", "java.lang.Object",
                        "java.lang.String", "java.lang.Object"},
                treeMaker.Ident(jcClassDecl.getSimpleName()), returnStatement, execMethodAllName, names.fromString(jcVariableDecl.getName() + methodNameStr));
    }

    /**
     * 构造方法 方法最多只有2行代码，第一行是执行某方法传一些参数，第二个是return xx
     *
     * @param execFunparamsList    调用其他方法
     * @param genMethodParamsList
     * @param execMethodParamTypes
     * @param returnMethodType
     * @param returnStatement
     * @param execMethodAllName
     * @return
     */
    private JCTree.JCMethodDecl genMethod(List<JCTree.JCExpression> execFunparamsList
            , List<JCTree.JCVariableDecl> genMethodParamsList, String[] execMethodParamTypes,
                                          JCTree.JCExpression returnMethodType,
                                          JCTree.JCReturn returnStatement, String execMethodAllName, Name methodName) {

        //语句列表  先执行语句在返回
        ListBuffer<JCTree.JCStatement> statments = new ListBuffer<JCTree.JCStatement>();
        if (execFunparamsList != null) {
            JCTree.JCMethodInvocation callMethod = AstUtil.callMethod(treeMaker, elementUtils, execMethodAllName,
                    execMethodParamTypes, execFunparamsList);
            statments.append(treeMaker.Exec(callMethod));
        }
        statments.append(returnStatement);

        //方法访问修饰符: public
        JCTree.JCModifiers modifiers = treeMaker.Modifiers(Flags.PUBLIC);


        //生成方法体
        JCTree.JCBlock body = treeMaker.Block(0, statments.toList());
        //泛型参数列表
        List<JCTree.JCTypeParameter> methodGenericParamList = List.nil();

        //异常抛出列表
        List<JCTree.JCExpression> thrownCauseList = List.nil();
        return treeMaker.MethodDef(
                modifiers,
                methodName,
                returnMethodType,
                methodGenericParamList,
                genMethodParamsList,
                thrownCauseList,
                body,
                null
        );
    }

    /**
     * newOBJ 方法生成 这个是个静态方法
     *
     * @param jcClassDecl
     * @return
     */
    public JCTree.JCMethodDecl genNewObjMethod(JCTree.JCClassDecl jcClassDecl) {
        // 生成 调用方法的参数列表
        List<JCTree.JCExpression> execFunparamsList = List.nil();
        execFunparamsList = execFunparamsList.append(treeMaker.Literal(jcClassDecl.sym.toString()));

        //方法参数: 方法的形式参数
        JCTree.JCVariableDecl tempObj = treeMaker.VarDef(
                treeMaker.Modifiers(Flags.PARAMETER, List.nil()),  //访问变量标识符
                names.fromString("tempObj"),        //变量名
                AstUtil.memberAccess(treeMaker, elementUtils, "java.lang.Object"),     //变量类型
                AstUtil.callMethod(treeMaker, elementUtils, "com.baomidou.mybatisplus.ext.util.Funtions.newOBJ",
                        new String[]{"java.lang.String"}, execFunparamsList));     //变量初始值

        JCTree.JCVariableDecl result = treeMaker.VarDef(
                treeMaker.Modifiers(Flags.PARAMETER, List.nil()),  //访问变量标识符
                names.fromString("result"),        //变量名
                AstUtil.memberAccess(treeMaker, elementUtils, jcClassDecl.sym.toString()),     //变量类型
                treeMaker.Ident(names.fromString("tempObj")));     //变量初始值

        //添加一个强制转换
        result.init = treeMaker.TypeCast(AstUtil.memberAccess(treeMaker, elementUtils, jcClassDecl.sym.toString()), treeMaker.Ident(names.fromString("tempObj")));

        //生成return语句: return result;
        JCTree.JCReturn returnStatement = treeMaker.Return(treeMaker.Ident(names.fromString("result")));
        ListBuffer<JCTree.JCStatement> statments = new ListBuffer<JCTree.JCStatement>();
        statments = statments.append(tempObj);
        statments = statments.append(result);
        statments = statments.append(returnStatement);
        //生成方法体
        JCTree.JCBlock body = treeMaker.Block(0, statments.toList());
        //方法访问修饰符: public static
        JCTree.JCModifiers modifiers = treeMaker.Modifiers(Flags.PUBLIC + Flags.STATIC);
        //不需要参数
        List<JCTree.JCVariableDecl> genMethodParamsList = List.nil();
        JCTree.JCMethodDecl methodDecl = treeMaker.MethodDef(
                modifiers,
                names.fromString("newOBJ"),
                treeMaker.Ident(jcClassDecl.getSimpleName()),
                List.nil(),
                List.nil(),
                List.nil(),
                body,
                null
        );
        return methodDecl;
    }


    /**
     * 生成数据库增删改查方法
     *
     * @param jcClassDecl
     * @param execMethodReturnType 返回值类型
     * @param execMethodName       执行方法名
     * @param execMethodParamTypes 参数类型
     * @param isHashFields         是否接收String[] fields参数
     * @param isOne                是否返回一个对象(比如 返回一个Student)
     * @param methodName           方法名
     * @return
     */
    public JCTree.JCMethodDecl genDBOperatorMethod(JCTree.JCClassDecl jcClassDecl, String execMethodReturnType, String execMethodName, String[] execMethodParamTypes, boolean isHashFields, boolean isOne, String methodName) {
        // 生成 调用方法的参数列表
        List<JCTree.JCExpression> execFunparamsList = List.nil();
        // 参数添加this.wrapperVars
        execFunparamsList = execFunparamsList.append(treeMaker.Select(
                treeMaker.Ident(names.fromString("this"))
                , names.fromString("wrapper")
        ));

        // po
        execFunparamsList = execFunparamsList.append(treeMaker.Ident(names.fromString("this")));
        if (isHashFields) {
            // 操作符
            execFunparamsList = execFunparamsList.append(treeMaker.Ident(names.fromString("fields")));
        }
        ListBuffer<JCTree.JCStatement> statments = new ListBuffer<JCTree.JCStatement>();
        //不是一个PO 的时候不需要强制转换部分的代码
        if (!isOne) {
            //方法参数: 方法的形式参数
            JCTree.JCVariableDecl result = treeMaker.VarDef(
                    treeMaker.Modifiers(Flags.PARAMETER, List.nil()),  //访问变量标识符
                    names.fromString("result"),        //变量名
                    AstUtil.memberAccess(treeMaker, elementUtils, execMethodReturnType),     //变量类型
                    AstUtil.callMethod(treeMaker, elementUtils, execMethodName,
                            execMethodParamTypes, execFunparamsList));     //变量初始值
            //生成return语句: return result;
            JCTree.JCReturn returnStatement = treeMaker.Return(treeMaker.Ident(names.fromString("result")));

            statments = statments.append(result);
            statments = statments.append(returnStatement);
        } else {
            //是一个PO的时候需要强制转换
            //方法参数: 方法的形式参数
            JCTree.JCVariableDecl tempObj = treeMaker.VarDef(
                    treeMaker.Modifiers(Flags.PARAMETER, List.nil()),  //访问变量标识符
                    names.fromString("tempObj"),        //变量名
                    AstUtil.memberAccess(treeMaker, elementUtils, "java.lang.Object"),     //变量类型
                    AstUtil.callMethod(treeMaker, elementUtils, execMethodName,
                            execMethodParamTypes, execFunparamsList));     //变量初始值
            //无视这段重复把-- 就当你没看到
            JCTree.JCVariableDecl result = treeMaker.VarDef(
                    treeMaker.Modifiers(Flags.PARAMETER, List.nil()),  //访问变量标识符
                    names.fromString("result"),        //变量名
                    AstUtil.memberAccess(treeMaker, elementUtils, jcClassDecl.sym.toString()),     //变量类型
                    treeMaker.Ident(names.fromString("tempObj")));     //变量初始值

            //添加一个强制转换
            result.init = treeMaker.TypeCast(AstUtil.memberAccess(treeMaker, elementUtils, jcClassDecl.sym.toString()), treeMaker.Ident(names.fromString("tempObj")));

            //生成return语句: return result;
            JCTree.JCReturn returnStatement = treeMaker.Return(treeMaker.Ident(names.fromString("result")));

            statments = statments.append(tempObj);
            statments = statments.append(result);
            statments = statments.append(returnStatement);
        }
        //生成方法体
        JCTree.JCBlock body = treeMaker.Block(0, statments.toList());
        //方法访问修饰符: public
        JCTree.JCModifiers modifiers = treeMaker.Modifiers(Flags.PUBLIC);
        List<JCTree.JCVariableDecl> methodParams = List.nil();

        if (isHashFields) {
            //方法参数: 方法的形式参数
            JCTree.JCVariableDecl param = treeMaker.VarDef(
                    treeMaker.Modifiers(Flags.PARAMETER, List.nil()),  //访问变量标识符
                    names.fromString("fields"),        //变量名
                    treeMaker.TypeArray(AstUtil.memberAccess(treeMaker, elementUtils, "java.lang.String")),     //变量类型
                    null        //变量初始值
            );
            methodParams = List.of(param);
        }

        JCTree.JCMethodDecl methodDecl = treeMaker.MethodDef(
                modifiers,
                names.fromString(methodName),
                AstUtil.memberAccess(treeMaker, elementUtils, execMethodReturnType),
                List.nil(),
                methodParams,
                List.nil(),
                body,
                null
        );
        return methodDecl;
    }

    /**
     * 根据设置的参数查询集合，指定字段
     *
     * @param jcClassDecl
     * @return
     */
    public JCTree.JCMethodDecl genListSettFieldsMethod(JCTree.JCClassDecl jcClassDecl) {
        return genDBOperatorMethod(jcClassDecl, "java.util.List", "com.baomidou.mybatisplus.ext.util.Funtions.list", new String[]{
                "com.baomidou.mybatisplus.core.conditions.query.QueryWrapper", "java.lang.Object", "java.lang.Object"
        }, true, false, "list");
    }

    /**
     * 根据设置的参数查询集合
     *
     * @param jcClassDecl
     * @return
     */
    public JCTree.JCMethodDecl genListMethod(JCTree.JCClassDecl jcClassDecl) {
        return genDBOperatorMethod(jcClassDecl, "java.util.List", "com.baomidou.mybatisplus.ext.util.Funtions.list", new String[]{
                "com.baomidou.mybatisplus.core.conditions.query.QueryWrapper", "java.lang.Object",
        }, false, false, "list");
    }

    /**
     * 根据条件查询单个对象，指定字段
     *
     * @param jcClassDecl
     * @return
     */
    public JCTree.JCMethodDecl genOneSettFieldsMethod(JCTree.JCClassDecl jcClassDecl) {
        return genDBOperatorMethod(jcClassDecl, jcClassDecl.getSimpleName().toString(), "com.baomidou.mybatisplus.ext.util.Funtions.one", new String[]{
                "com.baomidou.mybatisplus.core.conditions.query.QueryWrapper", "java.lang.Object", "java.lang.Object"
        }, true, true, "one");
    }

    /**
     * 根据条件查询单个对象
     *
     * @param jcClassDecl
     * @return
     */
    public JCTree.JCMethodDecl genOneMethod(JCTree.JCClassDecl jcClassDecl) {
        return genDBOperatorMethod(jcClassDecl, jcClassDecl.getSimpleName().toString(), "com.baomidou.mybatisplus.ext.util.Funtions.one", new String[]{
                "com.baomidou.mybatisplus.core.conditions.query.QueryWrapper", "java.lang.Object"
        }, false, true, "one");
    }

    /**
     * 根据条件查询数量
     *
     * @param jcClassDecl
     * @return
     */
    public JCTree.JCMethodDecl genCountMethod(JCTree.JCClassDecl jcClassDecl) {
        return genDBOperatorMethod(jcClassDecl, "java.lang.Long", "com.baomidou.mybatisplus.ext.util.Funtions.count", new String[]{
                "com.baomidou.mybatisplus.core.conditions.query.QueryWrapper", "java.lang.Object"
        }, false, false, "count");
    }

    /**
     * 根据条件更新，po里有哪些字段只更新哪些字段 返回受影响行数
     *
     * @param jcClassDecl
     * @return
     */
    public JCTree.JCMethodDecl genUpdateMethod(JCTree.JCClassDecl jcClassDecl) {
        return genDBOperatorMethod(jcClassDecl, "java.lang.Integer", "com.baomidou.mybatisplus.ext.util.Funtions.update", new String[]{
                "com.baomidou.mybatisplus.core.conditions.query.QueryWrapper", "java.lang.Object"
        }, false, false, "update");
    }

    /**
     * 根据条件删除返回受影响行数
     *
     * @param jcClassDecl
     * @return
     */
    public JCTree.JCMethodDecl genDeleteMethod(JCTree.JCClassDecl jcClassDecl) {
        return genDBOperatorMethod(jcClassDecl, "java.lang.Integer", "com.baomidou.mybatisplus.ext.util.Funtions.delete", new String[]{
                "com.baomidou.mybatisplus.core.conditions.query.QueryWrapper", "java.lang.Object"
        }, false, false, "delete");
    }

    /**
     * 判断是否是字符串 字符串可以like
     *
     * @param jcVariableDecl 字段
     * @param jcClassDecl    类
     * @return
     */
    public boolean checkIsCharset(JCTree.JCVariableDecl jcVariableDecl, JCTree.JCClassDecl jcClassDecl) {

        String typeName = jcVariableDecl.vartype.type.toString();
        try {
            Class clazz = Class.forName(typeName);
            return CharSequence.class.isAssignableFrom(clazz);
        } catch (ClassNotFoundException e) {
            return false;
        }
    }

    /**
     * 判断是否需要处理此字段
     *
     * @param jcVariableDecl 字段
     * @param jcClassDecl    类
     * @return
     */
    public boolean isHandle(JCTree.JCVariableDecl jcVariableDecl, JCTree.JCClassDecl jcClassDecl) {
        if (jcVariableDecl.vartype == null || jcVariableDecl.vartype.type == null) {
            return false;
        }
        String typeName = jcVariableDecl.vartype.type.toString();
        //不是Java开头的不处理
        if (!typeName.startsWith("java.")) {
            return false;
        }
        try {
            Class clazz = Class.forName(typeName);
            return Comparable.class.isAssignableFrom(clazz);
        } catch (ClassNotFoundException e) {
            return false;
        }
    }


    /**
     * 生成eq方法
     *
     * @param jcVariableDecl 属性
     * @param jcClassDecl    类
     * @return
     */
    private JCTree.JCMethodDecl genEQMethod(JCTree.JCVariableDecl jcVariableDecl, JCTree.JCClassDecl jcClassDecl) {
        return genMethod(jcVariableDecl, jcClassDecl,
                true, "EQ", "eq");
    }

    /**
     * 生成neq方法
     *
     * @param jcVariableDecl 属性
     * @param jcClassDecl    类
     * @return
     */
    private JCTree.JCMethodDecl genNEQMethod(JCTree.JCVariableDecl jcVariableDecl, JCTree.JCClassDecl jcClassDecl) {
        return genMethod(jcVariableDecl, jcClassDecl,
                true, "NE", "ne");
    }

    /**
     * 生成like方法
     *
     * @param jcVariableDecl 属性
     * @param jcClassDecl    类
     * @return
     */
    private JCTree.JCMethodDecl genLikeMethod(JCTree.JCVariableDecl jcVariableDecl, JCTree.JCClassDecl jcClassDecl) {
        return genMethod(jcVariableDecl, jcClassDecl,
                true, "Like", "like");
    }

    /**
     * 生成LikeRight方法
     *
     * @param jcVariableDecl 属性
     * @param jcClassDecl    类
     * @return
     */
    private JCTree.JCMethodDecl genLikeRightMethod(JCTree.JCVariableDecl jcVariableDecl, JCTree.JCClassDecl jcClassDecl) {
        return genMethod(jcVariableDecl, jcClassDecl,
                true, "LikeRight", "likeRight");
    }

    /**
     * 生成LikeLeft方法
     *
     * @param jcVariableDecl 属性
     * @param jcClassDecl    类
     * @return
     */
    private JCTree.JCMethodDecl genLikeLeftMethod(JCTree.JCVariableDecl jcVariableDecl, JCTree.JCClassDecl jcClassDecl) {
        return genMethod(jcVariableDecl, jcClassDecl,
                true, "LikeLeft", "likeLeft");
    }

    /**
     * 生成NotLike方法
     *
     * @param jcVariableDecl 属性
     * @param jcClassDecl    类
     * @return
     */
    private JCTree.JCMethodDecl genNotLikeMethod(JCTree.JCVariableDecl jcVariableDecl, JCTree.JCClassDecl jcClassDecl) {
        return genMethod(jcVariableDecl, jcClassDecl,
                true, "NotLike", "notLike");
    }


    private JCTree.JCMethodDecl genGEMethod(JCTree.JCVariableDecl jcVariableDecl, JCTree.JCClassDecl jcClassDecl) {
        return genMethod(jcVariableDecl, jcClassDecl,
                true, "GE", "ge");
    }


    private JCTree.JCMethodDecl genGTMethod(JCTree.JCVariableDecl jcVariableDecl, JCTree.JCClassDecl jcClassDecl) {
        return genMethod(jcVariableDecl, jcClassDecl,
                true, "GT", "gt");
    }

    private JCTree.JCMethodDecl genLEMethod(JCTree.JCVariableDecl jcVariableDecl, JCTree.JCClassDecl jcClassDecl) {
        return genMethod(jcVariableDecl, jcClassDecl,
                true, "LE", "le");
    }

    private JCTree.JCMethodDecl genLTMethod(JCTree.JCVariableDecl jcVariableDecl, JCTree.JCClassDecl jcClassDecl) {
        return genMethod(jcVariableDecl, jcClassDecl,
                true, "LT", "lt");
    }

    private JCTree.JCMethodDecl genOrderByAscMethod(JCTree.JCVariableDecl jcVariableDecl, JCTree.JCClassDecl jcClassDecl) {
        return genMethod(jcVariableDecl, jcClassDecl,
                false, "OrderByAsc", "orderByAsc");
    }

    private JCTree.JCMethodDecl genOrderByDescMethod(JCTree.JCVariableDecl jcVariableDecl, JCTree.JCClassDecl jcClassDecl) {
        return genMethod(jcVariableDecl, jcClassDecl,
                false, "OrderByDesc", "orderByDesc");
    }

    private JCTree.JCMethodDecl genIsNullMethod(JCTree.JCVariableDecl jcVariableDecl, JCTree.JCClassDecl jcClassDecl) {
        return genMethod(jcVariableDecl, jcClassDecl,
                false, "IsNull", "isNull");
    }

    private JCTree.JCMethodDecl genNotNullMethod(JCTree.JCVariableDecl jcVariableDecl, JCTree.JCClassDecl jcClassDecl) {
        return genMethod(jcVariableDecl, jcClassDecl,
                false, "NotNull", "notNull");
    }

    private JCTree.JCMethodDecl genInMethod(JCTree.JCVariableDecl jcVariableDecl, JCTree.JCClassDecl jcClassDecl) {
        return genParamCollectionMethod(jcVariableDecl, jcClassDecl, "In", "in");
    }

    private JCTree.JCMethodDecl genNotInMethod(JCTree.JCVariableDecl jcVariableDecl, JCTree.JCClassDecl jcClassDecl) {
        return genParamCollectionMethod(jcVariableDecl, jcClassDecl, "NotIn", "notIn");
    }

    private JCTree.JCMethodDecl genBetweenMethod(JCTree.JCVariableDecl jcVariableDecl, JCTree.JCClassDecl jcClassDecl) {
        return gen2ParamMethod(jcVariableDecl, jcClassDecl, "Between", "between");
    }

    private JCTree.JCMethodDecl genNotBetweenMethod(JCTree.JCVariableDecl jcVariableDecl, JCTree.JCClassDecl jcClassDecl) {
        return gen2ParamMethod(jcVariableDecl, jcClassDecl, "NotBetween", "notBetween");
    }


    /**
     * 生成asWrapper方法
     *
     * @param jcClassDecl 类
     * @return
     */
    private JCTree.JCMethodDecl genBean2WrapperMethod(JCTree.JCClassDecl jcClassDecl) {
        //生成return语句: return this;
        JCTree.JCReturn returnStatement = treeMaker.Return(
                treeMaker.Select(
                        treeMaker.Ident(names.fromString("this"))
                        , names.fromString("wrapper")
                )
        );
        return genMethod(null
                , List.nil(),
                null,
                AstUtil.memberAccess(treeMaker, elementUtils, "com.baomidou.mybatisplus.core.conditions.query.QueryWrapper"),
                returnStatement, null, names.fromString("bean2Wrapper"));
    }


}
